package com.idea.zd.sys.te;

import java.text.DecimalFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Maps;
import com.idea.zd.sys.util.DateUtil;
import com.idea.zd.sys.util.MD5Encrypt;



public class TeLaiDianCore {
	
	private static Logger log = LoggerFactory.getLogger(TeLaiDianCore.class);
	
	private static Random random = new Random();

	private static Map<String,String> map = new ConcurrentHashMap<String, String>(3);
	
	
	public static void main(String[] args) throws Exception {
		
//		   String dateStr = DateUtil.formatDate(new Date(), "yyyyMMddHHmmss");
//		getSeq(dateStr);
//		queryToken();
//		System.out.println(getToken());
//		getTokenBody("395815801");
//		queryStationInfo(queryToken(),1,10);
//		String StartChargeSeq = TeLaiDianConfig.OPERATOR_ID + SerialNumberGenerator.generateChargeNo();
//		System.out.println("StartChargeSeq="+StartChargeSeq);
		
//		queryStationStatus(new String[]{"3702120244"}, queryToken()); 
//		queryEquipAuth("355306869C20170313155209050","3702120244904",queryToken() );
		
		//queryStartCharge("123456789201704131711223214","3702120244904", "Bearer " +"08ypnJuQHK9uRuT25ciRNvs4vPWzeETwkkGzoAiLR8zj53l6P8N7ooMnXg96dieQ");
		queryStopCharge("123456789201704131711223214","3702120244102", "Bearer " +"0HQg6LdPzrHbmWPvDv1T7C4FXZmT93dClwsaXBSwzvJV7xdC6tbfVa2LHFUg443E");
		
//		String str ="{\"StartChargeSeq\":\"355306869C20170315180853873\",\"ConnectorID\":\"3702120244A03\",\"StartTime\":\"2017-03-15 18:08:35\",\"EndTime\":\"2017-03-15 18:09:19\",\"TotalPower\":0.00,\"TotalElecMoney\":0.00,\"TotalSeviceMoney\":0.00,\"TotalMoney\":0.00,\"StopReason\":99,\"SumPeriod\":0,\"ChargeDetails\":[]}";
//		Map<String,Object> map = JSON.parseObject(str, Map.class);
//		CarChargeLog carChargeLog = new CarChargeLog();
//		
//		carChargeLog.setTotalPower(Double.valueOf(map.get("TotalPower").toString()));
////		carChargeLog.setChargeType(orderInfo.getChargeType());
//		carChargeLog.setServiceMoney(Double.valueOf(map.get("TotalSeviceMoney").toString()));
//		carChargeLog.setElectricMoney(Double.valueOf(map.get("TotalElecMoney").toString()));
//		carChargeLog.setTotalMoney(Double.valueOf(map.get("TotalMoney").toString()));
////		carChargeLog.setSoc(orderInfo.getSoc());
//		
//		carChargeLog.setEndReason(String.valueOf(map.get("StopReason")));
//		carChargeLog.setStatus(2);
	}
	/**
	 * 生成充电流水号
	 * @return
	 */
	private static String generateChargeNo(){
		DecimalFormat df = new DecimalFormat("000");
		return "C"+DateUtil.formatDate(new Date(), "yyyyMMddHHmmss") + df.format(random.nextInt(999));
	}
	
	public static String getChargeSeq(){
		return TeLaiDianConfig.OPERATOR_ID + generateChargeNo();
	}
	
   public static String generateSecurityParam(String jsonParam, String aesKey, String aesIV, String signKey) throws Exception{
	   System.out.println("generateSecurityParam="+jsonParam);
	   JSONObject paramObj = new JSONObject();   
       paramObj.put(Dic.OperatorID, TeLaiDianConfig.OPERATOR_ID);
       paramObj.put(Dic.Data, AESUtil.Encrypt(jsonParam, aesKey, aesIV));
       String dateStr = DateUtil.formatDate(new Date(), "yyyyMMddHHmmss");
       paramObj.put(Dic.TimeStamp, dateStr);
       paramObj.put(Dic.Seq, getSeq(dateStr));
	   
       String signMsg =
    		   paramObj.getString(Dic.OperatorID) +
               paramObj.getString(Dic.Data) +
               paramObj.getString(Dic.TimeStamp) +
               paramObj.getString(Dic.Seq);

           paramObj.put(Dic.Sig, HMacMD5.getHmacMd5Str(signKey, signMsg));
	   
	   return paramObj.toString();
   }
   
   /**
    * 生成token
    * @return
    */
   public static String getToken(){
	   String AccessToken = MD5Encrypt.MD5Encode(String.valueOf(random.nextInt(999999))) +  MD5Encrypt.MD5Encode(String.valueOf(random.nextInt(999999)));
	   return AccessToken;
   }

   /**
    * 对外提供tokenBody
    * @return
    * @throws Exception
    */
   
   public static String getTokenBody(String result,String AccessToken) throws Exception{
	   HashMap<String,Object> retObj = JSON.parseObject(result,HashMap.class);
	   String OperatorID = (String)retObj.get(Dic.OperatorID);
	   Map<String , Object> map = Maps.newHashMap();
	   map.put(Dic.OperatorID, OperatorID);
	   map.put(Dic.SuccStat, 0);
	   map.put(Dic.AccessToken, AccessToken);
	   map.put(Dic.TokenAvailableTime, 7200);
	   map.put(Dic.FailReason, 0);
  
	   JSONObject paramObj = new JSONObject();   
       paramObj.put(Dic.Ret, 0);
       paramObj.put(Dic.Msg, "");
       paramObj.put(Dic.Data, AESUtil.Encrypt(JSON.toJSONString(map), TeLaiDianConfig.AES_KEY, TeLaiDianConfig.AES_IV));
	   
       String signMsg =
    		   paramObj.getString(Dic.Ret) +
    		   paramObj.getString(Dic.Msg) +
               paramObj.getString(Dic.Data);

           paramObj.put(Dic.Sig, HMacMD5.getHmacMd5Str(TeLaiDianConfig.SIGN_KEY, signMsg));
	   
	   
//	   System.out.println("bodyData="+paramObj.toJSONString());
	   return paramObj.toJSONString();
   }
   
   public static NotifyResult notificationBody(String result) throws Exception{
	   HashMap<String,Object> retObj = JSON.parseObject(result,HashMap.class);
	   String Data = (String)retObj.get(Dic.Data);
	   Data = AESUtil.Decrypt(Data, TeLaiDianConfig.AES_KEY, TeLaiDianConfig.AES_IV);
	   log.info("Data="+Data);
	   
	   HashMap parseData = JSON.parseObject(Data,HashMap.class);
	   String StartChargeSeq = (String)parseData.get(Dic.StartChargeSeq);
	   
	   Map<String , Object> map = Maps.newHashMap();
	   map.put(Dic.SuccStat, 0);
	   map.put(Dic.StartChargeSeq, StartChargeSeq);
	   map.put(Dic.FailReason, 0);
	   
	   JSONObject paramObj = new JSONObject();   
       paramObj.put(Dic.Ret, 0);
       paramObj.put(Dic.Msg, "");
       paramObj.put(Dic.Data, AESUtil.Encrypt(JSON.toJSONString(map), TeLaiDianConfig.AES_KEY, TeLaiDianConfig.AES_IV));
      
       String signMsg =
    		   paramObj.getString(Dic.Ret) +
    		   paramObj.getString(Dic.Msg) +
               paramObj.getString(Dic.Data);

           paramObj.put(Dic.Sig, HMacMD5.getHmacMd5Str(TeLaiDianConfig.SIGN_KEY, signMsg));

       //System.out.println("bodyData="+paramObj.toJSONString());
	   return new NotifyResult(StartChargeSeq,paramObj.toJSONString());
   }
   
	
	/**
	 * jsonParam={"OperatorSecret":"1234567890abcdef","OperatorID":"355306869"}
		{"TimeStamp":"20170216141513","Seq":"0001",Dic.Data:"BmuQPtmtMfSqKqTPqiWVUAYFBN6VGfUH7INq04il+WN/cUIZr3iVlfJoY52ESRFUPfXRRMWHjixY\nseyyW4ImNw==","OperatorID":"355306869","Sig":"3C22D37E51DACD5C4BA522CF85914738"}
		{
		  "Ret": 0,
		  "Msg": "",
		  Dic.Data: "uxeKP0ezR5yL8xSg4/ZCDq2IxrUV8HUxj2zrRt2dYn07sVhZlJMSqCe5/E925cHDZsAijNDB33D5wU+M0yOYZGfbp1K5VTE6OwlvhcMv/QcSh1YvQ7XcVhXqrhuk4ifYBaz8Pgwztz10lf8mtt9qqVBRJO1HzXYthurHAgh788264a72b/bywrOtWmJWyte4a40rikO6MeBtoPsUC2ItY3sFx0r+bR/SbvH4NDgZvoZkNBhmrev0zueqol4YHCps",
		  "Sig": "D30AE3FEB767967762FB198D25704E3A"
		}
	 * @return
	 * @throws Exception
	 */
	public static String queryToken() throws Exception{
		String url = TeLaiDianConfig.URL + "query_token";
		Map<String , Object> map = Maps.newHashMap();
		map.put(Dic.OperatorID, TeLaiDianConfig.OPERATOR_ID);
		map.put(Dic.OperatorSecret, TeLaiDianConfig.OPERATOR_SECRET);
		 //生成加密签名参数
        String bodyData = generateSecurityParam(JSON.toJSONString(map), TeLaiDianConfig.AES_KEY, TeLaiDianConfig.AES_IV, TeLaiDianConfig.SIGN_KEY);
     
		String result = PowerHttpClient.doPost(url,bodyData,"");
		System.out.println("回调 queryToken="+result);
		 if (result != null){
			 HashMap<String,Object> retObj = JSON.parseObject(result,HashMap.class);
			if (Integer.parseInt(retObj.get("Ret").toString()) == 0) {
				String plaintStr = AESUtil.Decrypt(retObj.get(Dic.Data).toString(), TeLaiDianConfig.AES_KEY, TeLaiDianConfig.AES_IV);//对返回结果解密
				System.out.println("plaintStr="+plaintStr);
				HashMap<String,Object> dataMap = JSON.parseObject(plaintStr,HashMap.class);
				String accessToken = dataMap.get("AccessToken").toString();//Token值
				return accessToken;
			}
		 }
		return null;
	}
	
	/**
	 *  查询充电站信息
	 * @param token
	 * @throws Exception 
	 */
	public static TldStationInfoJsonVo queryStationInfo(String token,Integer PageNo,Integer PageSize) throws Exception{
		String url = TeLaiDianConfig.URL + "query_stations_info";
		Map<String , Object> map = Maps.newHashMap();
		map.put(Dic.PageNo, PageNo);
		map.put(Dic.PageSize, PageSize);
		String bodyData = generateSecurityParam(JSON.toJSONString(map), TeLaiDianConfig.AES_KEY, TeLaiDianConfig.AES_IV, TeLaiDianConfig.SIGN_KEY);
		String result = PowerHttpClient.doPost(url,bodyData,token);
		TldStationInfoJsonVo tldStationInfoJsonVo = null;
		 if (result != null){
			 HashMap<String,Object> retObj = JSON.parseObject(result,HashMap.class);
			 String plaintStr = AESUtil.Decrypt(retObj.get(Dic.Data).toString(), TeLaiDianConfig.AES_KEY, TeLaiDianConfig.AES_IV);//对返回结果解密
			 log.info("plaintStr="+plaintStr); 
			
			 tldStationInfoJsonVo = JSON.parseObject(plaintStr,TldStationInfoJsonVo.class);
//			 System.out.println(tldStationInfoJsonVo);
			 
		 }
		 return tldStationInfoJsonVo;
	}
	/**
	 * 请求认证
	 * @throws Exception 
	 * 
	 */
	public static NotifyResult queryEquipAuth(String EquipAuthSeq,String ConnectorID,String token) throws Exception{
		String url = TeLaiDianConfig.URL + "query_equip_auth";
		Map<String , Object> map = Maps.newHashMap();
		map.put(Dic.EquipAuthSeq, EquipAuthSeq);
		map.put(Dic.ConnectorID, ConnectorID);
		
		String bodyData = generateSecurityParam(JSON.toJSONString(map), TeLaiDianConfig.AES_KEY, TeLaiDianConfig.AES_IV, TeLaiDianConfig.SIGN_KEY);
		String result = PowerHttpClient.doPost(url,bodyData,token);

		log.info("鉴权验证结果="+result);
		NotifyResult notifyResult = new NotifyResult();
		
		 if (result != null){
			 HashMap<String,Object> retObj = JSON.parseObject(result,HashMap.class);
			 String plaintStr = AESUtil.Decrypt(retObj.get(Dic.Data).toString(), TeLaiDianConfig.AES_KEY, TeLaiDianConfig.AES_IV);//对返回结果解密
			
			 System.out.println("plaintStr="+plaintStr);
			 retObj = JSON.parseObject(plaintStr,HashMap.class);
			 
			 Integer SuccStat = Integer.parseInt(retObj.get(Dic.SuccStat).toString());
			 Integer FailReason = Integer.parseInt(retObj.get(Dic.FailReason).toString());
			 notifyResult.setSuccStat(SuccStat);
			 notifyResult.setFailReason(FailReason);
			 
		 }
		 return notifyResult;
	}
	
	public static TldStationStatusInfoJsonVo queryStationStatus(String[] StationID,String token) throws Exception{
		
		String url = TeLaiDianConfig.URL + "query_station_status";
		Map<String , Object> map = Maps.newHashMap();
		map.put("StationIDs", StationID);
		
		String bodyData = generateSecurityParam(JSON.toJSONString(map), TeLaiDianConfig.AES_KEY, TeLaiDianConfig.AES_IV, TeLaiDianConfig.SIGN_KEY);
		String result = PowerHttpClient.doPost(url,bodyData,token);
//		System.out.println(result);
		TldStationStatusInfoJsonVo jsonVo = null;
		 if (result != null){
			 HashMap<String,Object> retObj = JSON.parseObject(result,HashMap.class);
			 String plaintStr = AESUtil.Decrypt(retObj.get(Dic.Data).toString(), TeLaiDianConfig.AES_KEY, TeLaiDianConfig.AES_IV);//对返回结果解密
//			 System.out.println("plaintStr="+plaintStr);
			 jsonVo = JSON.parseObject(plaintStr, TldStationStatusInfoJsonVo.class);
		 }
		 return jsonVo;
	}
	
	
	public static NotifyResult queryStartCharge(String StartChargeSeq,String ConnectorID,String token) throws Exception {
		String url = TeLaiDianConfig.URL + "query_start_charge";
		Map<String , Object> map = Maps.newHashMap();
		map.put(Dic.StartChargeSeq, StartChargeSeq);
		map.put(Dic.ConnectorID, ConnectorID);
		map.put(Dic.QRCode, "");
		
		String bodyData = generateSecurityParam(JSON.toJSONString(map), TeLaiDianConfig.AES_KEY, TeLaiDianConfig.AES_IV, TeLaiDianConfig.SIGN_KEY);
		String result = PowerHttpClient.doPost(url,bodyData,token);
		NotifyResult notifyResult = new NotifyResult();
		 if (result != null){
			 HashMap<String,Object> retObj = JSON.parseObject(result,HashMap.class);
			 String plaintStr = AESUtil.Decrypt(retObj.get(Dic.Data).toString(), TeLaiDianConfig.AES_KEY, TeLaiDianConfig.AES_IV);//对返回结果解密
			 
			 System.out.println("plaintStr="+plaintStr);
			 
			 retObj = JSON.parseObject(plaintStr,HashMap.class);
			 Integer SuccStat = Integer.parseInt(retObj.get(Dic.SuccStat).toString());
			 Integer FailReason = Integer.parseInt(retObj.get(Dic.FailReason).toString());
			 notifyResult.setSuccStat(SuccStat);
			 notifyResult.setFailReason(FailReason);
			 
		 }
		 return notifyResult;
	}
	
	
	public static boolean queryStopCharge(String StartChargeSeq ,String ConnectorID,String token) throws Exception{
		String url = TeLaiDianConfig.URL + "query_stop_charge";
		Map<String , Object> map = Maps.newHashMap();
		map.put(Dic.StartChargeSeq, StartChargeSeq);
		map.put(Dic.ConnectorID, ConnectorID);
		
		String bodyData = generateSecurityParam(JSON.toJSONString(map), TeLaiDianConfig.AES_KEY, TeLaiDianConfig.AES_IV, TeLaiDianConfig.SIGN_KEY);
		String result = PowerHttpClient.doPost(url,bodyData,token);
		System.out.println(result);
		
		 if (result != null){
			 HashMap<String,Object> retObj = JSON.parseObject(result,HashMap.class);
			 String plaintStr = AESUtil.Decrypt(retObj.get(Dic.Data).toString(), TeLaiDianConfig.AES_KEY, TeLaiDianConfig.AES_IV);//对返回结果解密
			
			 retObj = JSON.parseObject(plaintStr,HashMap.class);
			 Integer SuccStat = Integer.parseInt(retObj.get(Dic.SuccStat).toString());
			 if(SuccStat==Dic.SUCCESS){
				 return true;
			 }
		 }
		 return false;
	}
	
	
	
	
	  public static String getSeq(String timeStamp){
          
              if (map.containsKey(timeStamp)) {
                  Integer count = Integer.parseInt(map.get(timeStamp)) + 1;
                  switch (count.toString().length()) {
                      case 1:
                          map.put(timeStamp,"000" + count);
                          break;
                      case 2:
                    	  map.put(timeStamp,"00" + count);
                          break;
                      case 3:
                    	  map.put(timeStamp,"0" + count);
                          break;
                      case 4:
                    	  map.put(timeStamp,"" + count);
                          break;
                      default:
                    	  map.put(timeStamp,"" + count);
                          break;
                  }
                  return map.get(timeStamp);
              }else{
                  map.put(timeStamp, "0001");
                  return "0001";
              }
          }
	
}
